
// ===============================================================================================================
// -*- C++ -*-
//
// GameLevel.hpp - Base class describing a game level.
//
// Copyright (c) 2011 Guilherme R. Lampert
// guilherme.ronaldo.lampert@gmail.com
//
// This code is licenced under the MIT license.
//
// This software is provided "as is" without express or implied
// warranties. You may freely copy and compile this source into
// applications you distribute provided that the copyright text
// above is included in the resulting source code.
//
// ===============================================================================================================

#ifndef __GAME_LEVEL_HPP__
#define __GAME_LEVEL_HPP__

// STL vector class
#include <vector>

// Local includes
#include <Common.hpp>
#include <Vector.hpp>
#include <RefPtr.hpp>
#include <ReferenceCountable.hpp>

///
/// GameLevel -- Generic game level interface. Exposes basic game level routines.
///
class GameLevel : public ReferenceCountable {

public:

	enum Type { PROCEDURAL_TERRAIN };

	// Public Interface:

	/// Returns the level height at a givem X and Z pos.
	/// This is used to set the correct player Y position as he moves thru the level.
	virtual float GetHeightAt(float x, float z) const = 0;

	/// Get the map scale factor.
	virtual float GetScale(void) const = 0;

	/// Get the level maximum extents in the x, and z directions.
	virtual void GetExtents(int & max_x, int & max_z) const = 0;

	/// Get the game level type.
	virtual Type GetLevelType(void) const = 0;

	/// Checks if the level creation failed.
	virtual bool Fail(void) const = 0;

	// ReferenceCountable Methods:

	virtual unsigned long AddRef(void) const;
	virtual unsigned long Release(void) const;
	virtual unsigned long ReferenceCount(void) const;

	// Data Access:

	/// Get the level name.
	inline const std::string & GetName(void) const { return (name); };

	/// Gives a random x and z position in the game map. Also sets the y to a proper height.
	inline void GetRandomPos(Vec3 & pos, int max_x, int max_z) const
	{
		pos.x =  RandCoord(max_x);
		pos.z = -RandCoord(max_z);
		pos.y =  this->GetHeightAt(pos.x, pos.z);
	}

public:

	enum ObjectType {

		FLAME_FIRE,
		ENEMY_INSTANCE,
		AMMO_BOXES,
		SKY_BOX,
	};

	struct Object {

		void * objPointer;
		int type;
	};

	std::vector<Object> objects;

protected:

	virtual ~GameLevel(void);

	// Member Variables:

	std::string name;
};

///
/// Reference countable GameLevel pointer type.
///
typedef RefPtr<GameLevel> GameLevelPtr;

// ===============================================================================================================

#define NUM_BILLBOARDS 100
#define NUM_AMMO_BOXES 20
#define NUM_ENEMIES 3

///
/// LevelBuilder -- Builds a game level.
/// The level builder is a singleton.
///
class LevelBuilder {

public:

	// Public Interface:

	/// "Build" a game level by populating it with objects, enemies and other scene stuff.
	static bool Build(GameLevel * level);

	/// Get the builded game level.
	static GameLevel * GetGameLevel(void);

private:

	 LevelBuilder(void) { /**/ };
	~LevelBuilder(void) { /**/ };

	static GameLevel * myLevel;
};

#endif // __GAME_LEVEL_HPP__